import { AFFIX_TEMPLATE, AFFIX_REGEXP } from "../frame.config";
import NativeClient, { NativeClientIns, NCAPIStructure } from "./NativeClient";

/** 原生端行为模拟 */
class VirtualClient extends NativeClientIns {
	private static receive_call_list: Array<(api: string, response: Awaited<NCAPIStructure<any, any>['response']>)=>void> = [];

	public callStaticMethod(api: string, request: NCAPIStructure<any, any>['request']){
		VirtualClient.request(api, request);
	}

	public onReceiveMessage(callback: (api: string, response: Awaited<NCAPIStructure<any, any>['response']>)=>void){
		VirtualClient.receive_call_list.push(callback);
	}

	private static request(api: string, request: NCAPIStructure<any, any>['request']){
		api = api.replace(AFFIX_REGEXP, '$1');
		VirtualClient.virtualFunc(api, JSON.stringify(request));
	}

	private static response(api: string, json_string: string){
		api = AFFIX_TEMPLATE.replace('key', api);
		let response = JSON.parse(json_string) as Awaited<NCAPIStructure<any, any>['response']>;
		VirtualClient.receive_call_list.forEach(callback=>callback(api, response));
	}

    private static formatResponse(response: any){
        let list = [];

        if(typeof response == 'object' && !Array.isArray(response)){
            list.unshift(response);
        }

        while(list.length>0){
            let item = list.pop();
			if(Array.isArray(item)){
				item.forEach(el=>{
					if(typeof el == 'object'){
						list.push(el);
					}
				})
			}else if(item){
				for(let [key, value] of Object.entries(item)){
					if(typeof value == 'object'){
						list.push(value);
					}

					Reflect.deleteProperty(item, key);
					Reflect.set(item, AFFIX_TEMPLATE.replace('key', key), value);
				}
			}
        }

        return response;
    }

    private static parseRequest(request: any){
        let list = [];

        if(typeof request == 'object' && !Array.isArray(request)){
            list.unshift(request);
        }

        while(list.length>0){
            let item = list.pop();
			if(Array.isArray(item)){
				item.forEach(el=>{
					if(typeof el == 'object'){
						list.push(el);
					}
				})
			}else if(item){
				for(let [key, value] of Object.entries(item)){
					if(typeof value == 'object'){
						list.push(value);
					}

					Reflect.deleteProperty(item, key);
					Reflect.set(item, key.replace(AFFIX_REGEXP, '$1'), value);
				}
			}
        }

        return request;
    }

	/** 原生端功能模拟 */
	private static virtualFunc(api: string, json_string: string){
		if(!Reflect.has(VirtualClient, api)) return void 0;

		let request = JSON.parse(json_string) as NCAPIStructure<any, any>['request'];
		VirtualClient.parseRequest(request);
		let response: any = Reflect.apply(Reflect.get(VirtualClient, api), VirtualClient, [Object.assign({}, request)]);

		if(response){
			VirtualClient.formatResponse(response);
			VirtualClient.response(api, JSON.stringify(response));
		}
	}

	private static setRESData(response: any, data: any){
		Reflect.set(response, 'data', data);
	}

	/** 模拟广告行为 */
	private static AD(response: any){
		VirtualClient.setRESData(response, {
			status: 'ad-over',
		});
		return response;
	}

	/** 模拟本地化行为 */
	private static LocalLanguage(response: any){
		VirtualClient.setRESData(response, {
			countryCode: 'CN',
			languageCode: 'zh',
		});
		return response;
	}

	/** 模拟链接行为 */
	private static Link(response: any){
		window.open(response.data.url);
		return undefined;
	}

	/** 模拟获取设备ID */
	private static device_id(response: any){
		let virtual_device_ID = localStorage.getItem('VIRTUAL-DEVICE-ID');
		if(!virtual_device_ID){
			virtual_device_ID = [8, 4, 4, 4, 12].map(len=>mtec.string.random(len, 16).toUpperCase()).join('-');
			virtual_device_ID = '<chrome-virtual>['+virtual_device_ID+']';
			localStorage.setItem('VIRTUAL-DEVICE-ID', virtual_device_ID);
		}
		VirtualClient.setRESData(response, {
			device_id: virtual_device_ID,
		});
		return response;
	}

	/** 模拟奖励领取 */
	private static fruit(){
		return undefined;
	}

	/** 模拟弹窗浮层 */
	private static float(){
		return undefined;
	}

	private static set_clipboard(response: any){
		mtec.log.tag('设置剪贴板: green;', response.data.text);
		return undefined;
	}

	private static type(response: any){
		VirtualClient.setRESData(response, {
			type: 'B',
		});
		return response;
	}
}

NativeClient.initClient(platform=>platform=='virtual'?new VirtualClient():void 0);